1 package org.apache.lucene.util;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import java.util.Arrays;
21 import java.util.Collection;
22 import java.util.Comparator;
23
24
25
26
27
28
29
30 public final class ArrayUtil {
31
32
33 public static final int MAX_ARRAY_LENGTH = Integer.MAX_VALUE - RamUsageEstimator.NUM_BYTES_ARRAY_HEADER;
34
35 private ArrayUtil() {}
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public static int parseInt(char[] chars) throws NumberFormatException {
54 return parseInt(chars, 0, chars.length, 10);
55 }
56
57
58
59
60
61
62
63
64
65 public static int parseInt(char[] chars, int offset, int len) throws NumberFormatException {
66 return parseInt(chars, offset, len, 10);
67 }
68
69
70
71
72
73
74
75
76
77
78
79
80 public static int parseInt(char[] chars, int offset, int len, int radix)
81 throws NumberFormatException {
82 if (chars == null || radix < Character.MIN_RADIX
83 || radix > Character.MAX_RADIX) {
84 throw new NumberFormatException();
85 }
86 int i = 0;
87 if (len == 0) {
88 throw new NumberFormatException("chars length is 0");
89 }
90 boolean negative = chars[offset + i] == '-';
91 if (negative && ++i == len) {
92 throw new NumberFormatException("can't convert to an int");
93 }
94 if (negative == true){
95 offset++;
96 len--;
97 }
98 return parse(chars, offset, len, radix, negative);
99 }
100
101
102 private static int parse(char[] chars, int offset, int len, int radix,
103 boolean negative) throws NumberFormatException {
104 int max = Integer.MIN_VALUE / radix;
105 int result = 0;
106 for (int i = 0; i < len; i++){
107 int digit = Character.digit(chars[i + offset], radix);
108 if (digit == -1) {
109 throw new NumberFormatException("Unable to parse");
110 }
111 if (max > result) {
112 throw new NumberFormatException("Unable to parse");
113 }
114 int next = result * radix - digit;
115 if (next > result) {
116 throw new NumberFormatException("Unable to parse");
117 }
118 result = next;
119 }
120
121
122
123 if (!negative) {
124 result = -result;
125 if (result < 0) {
126 throw new NumberFormatException("Unable to parse");
127 }
128 }
129 return result;
130 }
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156 public static int oversize(int minTargetSize, int bytesPerElement) {
157
158 if (minTargetSize < 0) {
159
160 throw new IllegalArgumentException("invalid array size " + minTargetSize);
161 }
162
163 if (minTargetSize == 0) {
164
165 return 0;
166 }
167
168 if (minTargetSize > MAX_ARRAY_LENGTH) {
169 throw new IllegalArgumentException("requested array size " + minTargetSize + " exceeds maximum array in java (" + MAX_ARRAY_LENGTH + ")");
170 }
171
172
173
174
175 int extra = minTargetSize >> 3;
176
177 if (extra < 3) {
178
179
180
181 extra = 3;
182 }
183
184 int newSize = minTargetSize + extra;
185
186
187 if (newSize+7 < 0 || newSize+7 > MAX_ARRAY_LENGTH) {
188
189 return MAX_ARRAY_LENGTH;
190 }
191
192 if (Constants.JRE_IS_64BIT) {
193
194 switch(bytesPerElement) {
195 case 4:
196
197 return (newSize + 1) & 0x7ffffffe;
198 case 2:
199
200 return (newSize + 3) & 0x7ffffffc;
201 case 1:
202
203 return (newSize + 7) & 0x7ffffff8;
204 case 8:
205
206 default:
207
208 return newSize;
209 }
210 } else {
211
212 switch(bytesPerElement) {
213 case 2:
214
215 return (newSize + 1) & 0x7ffffffe;
216 case 1:
217
218 return (newSize + 3) & 0x7ffffffc;
219 case 4:
220 case 8:
221
222 default:
223
224 return newSize;
225 }
226 }
227 }
228
229 public static int getShrinkSize(int currentSize, int targetSize, int bytesPerElement) {
230 final int newSize = oversize(targetSize, bytesPerElement);
231
232
233
234 if (newSize < currentSize / 2)
235 return newSize;
236 else
237 return currentSize;
238 }
239
240 public static <T> T[] grow(T[] array, int minSize) {
241 assert minSize >= 0: "size must be positive (got " + minSize + "): likely integer overflow?";
242 if (array.length < minSize) {
243 return Arrays.copyOf(array, oversize(minSize, RamUsageEstimator.NUM_BYTES_OBJECT_REF));
244 } else
245 return array;
246 }
247
248 public static short[] grow(short[] array, int minSize) {
249 assert minSize >= 0: "size must be positive (got " + minSize + "): likely integer overflow?";
250 if (array.length < minSize) {
251 short[] newArray = new short[oversize(minSize, RamUsageEstimator.NUM_BYTES_SHORT)];
252 System.arraycopy(array, 0, newArray, 0, array.length);
253 return newArray;
254 } else
255 return array;
256 }
257
258 public static short[] grow(short[] array) {
259 return grow(array, 1 + array.length);
260 }
261
262 public static float[] grow(float[] array, int minSize) {
263 assert minSize >= 0: "size must be positive (got " + minSize + "): likely integer overflow?";
264 if (array.length < minSize) {
265 float[] newArray = new float[oversize(minSize, RamUsageEstimator.NUM_BYTES_FLOAT)];
266 System.arraycopy(array, 0, newArray, 0, array.length);
267 return newArray;
268 } else
269 return array;
270 }
271
272 public static float[] grow(float[] array) {
273 return grow(array, 1 + array.length);
274 }
275
276 public static double[] grow(double[] array, int minSize) {
277 assert minSize >= 0: "size must be positive (got " + minSize + "): likely integer overflow?";
278 if (array.length < minSize) {
279 double[] newArray = new double[oversize(minSize, RamUsageEstimator.NUM_BYTES_DOUBLE)];
280 System.arraycopy(array, 0, newArray, 0, array.length);
281 return newArray;
282 } else
283 return array;
284 }
285
286 public static double[] grow(double[] array) {
287 return grow(array, 1 + array.length);
288 }
289
290 public static short[] shrink(short[] array, int targetSize) {
291 assert targetSize >= 0: "size must be positive (got " + targetSize + "): likely integer overflow?";
292 final int newSize = getShrinkSize(array.length, targetSize, RamUsageEstimator.NUM_BYTES_SHORT);
293 if (newSize != array.length) {
294 short[] newArray = new short[newSize];
295 System.arraycopy(array, 0, newArray, 0, newSize);
296 return newArray;
297 } else
298 return array;
299 }
300
301 public static int[] grow(int[] array, int minSize) {
302 assert minSize >= 0: "size must be positive (got " + minSize + "): likely integer overflow?";
303 if (array.length < minSize) {
304 int[] newArray = new int[oversize(minSize, RamUsageEstimator.NUM_BYTES_INT)];
305 System.arraycopy(array, 0, newArray, 0, array.length);
306 return newArray;
307 } else
308 return array;
309 }
310
311 public static int[] grow(int[] array) {
312 return grow(array, 1 + array.length);
313 }
314
315 public static int[] shrink(int[] array, int targetSize) {
316 assert targetSize >= 0: "size must be positive (got " + targetSize + "): likely integer overflow?";
317 final int newSize = getShrinkSize(array.length, targetSize, RamUsageEstimator.NUM_BYTES_INT);
318 if (newSize != array.length) {
319 int[] newArray = new int[newSize];
320 System.arraycopy(array, 0, newArray, 0, newSize);
321 return newArray;
322 } else
323 return array;
324 }
325
326 public static long[] grow(long[] array, int minSize) {
327 assert minSize >= 0: "size must be positive (got " + minSize + "): likely integer overflow?";
328 if (array.length < minSize) {
329 long[] newArray = new long[oversize(minSize, RamUsageEstimator.NUM_BYTES_LONG)];
330 System.arraycopy(array, 0, newArray, 0, array.length);
331 return newArray;
332 } else
333 return array;
334 }
335
336 public static long[] grow(long[] array) {
337 return grow(array, 1 + array.length);
338 }
339
340 public static long[] shrink(long[] array, int targetSize) {
341 assert targetSize >= 0: "size must be positive (got " + targetSize + "): likely integer overflow?";
342 final int newSize = getShrinkSize(array.length, targetSize, RamUsageEstimator.NUM_BYTES_LONG);
343 if (newSize != array.length) {
344 long[] newArray = new long[newSize];
345 System.arraycopy(array, 0, newArray, 0, newSize);
346 return newArray;
347 } else
348 return array;
349 }
350
351 public static byte[] grow(byte[] array, int minSize) {
352 assert minSize >= 0: "size must be positive (got " + minSize + "): likely integer overflow?";
353 if (array.length < minSize) {
354 byte[] newArray = new byte[oversize(minSize, 1)];
355 System.arraycopy(array, 0, newArray, 0, array.length);
356 return newArray;
357 } else
358 return array;
359 }
360
361 public static byte[] grow(byte[] array) {
362 return grow(array, 1 + array.length);
363 }
364
365 public static byte[] shrink(byte[] array, int targetSize) {
366 assert targetSize >= 0: "size must be positive (got " + targetSize + "): likely integer overflow?";
367 final int newSize = getShrinkSize(array.length, targetSize, 1);
368 if (newSize != array.length) {
369 byte[] newArray = new byte[newSize];
370 System.arraycopy(array, 0, newArray, 0, newSize);
371 return newArray;
372 } else
373 return array;
374 }
375
376 public static boolean[] grow(boolean[] array, int minSize) {
377 assert minSize >= 0: "size must be positive (got " + minSize + "): likely integer overflow?";
378 if (array.length < minSize) {
379 boolean[] newArray = new boolean[oversize(minSize, 1)];
380 System.arraycopy(array, 0, newArray, 0, array.length);
381 return newArray;
382 } else
383 return array;
384 }
385
386 public static boolean[] grow(boolean[] array) {
387 return grow(array, 1 + array.length);
388 }
389
390 public static boolean[] shrink(boolean[] array, int targetSize) {
391 assert targetSize >= 0: "size must be positive (got " + targetSize + "): likely integer overflow?";
392 final int newSize = getShrinkSize(array.length, targetSize, 1);
393 if (newSize != array.length) {
394 boolean[] newArray = new boolean[newSize];
395 System.arraycopy(array, 0, newArray, 0, newSize);
396 return newArray;
397 } else
398 return array;
399 }
400
401 public static char[] grow(char[] array, int minSize) {
402 assert minSize >= 0: "size must be positive (got " + minSize + "): likely integer overflow?";
403 if (array.length < minSize) {
404 char[] newArray = new char[oversize(minSize, RamUsageEstimator.NUM_BYTES_CHAR)];
405 System.arraycopy(array, 0, newArray, 0, array.length);
406 return newArray;
407 } else
408 return array;
409 }
410
411 public static char[] grow(char[] array) {
412 return grow(array, 1 + array.length);
413 }
414
415 public static char[] shrink(char[] array, int targetSize) {
416 assert targetSize >= 0: "size must be positive (got " + targetSize + "): likely integer overflow?";
417 final int newSize = getShrinkSize(array.length, targetSize, RamUsageEstimator.NUM_BYTES_CHAR);
418 if (newSize != array.length) {
419 char[] newArray = new char[newSize];
420 System.arraycopy(array, 0, newArray, 0, newSize);
421 return newArray;
422 } else
423 return array;
424 }
425
426 public static int[][] grow(int[][] array, int minSize) {
427 assert minSize >= 0: "size must be positive (got " + minSize + "): likely integer overflow?";
428 if (array.length < minSize) {
429 int[][] newArray = new int[oversize(minSize, RamUsageEstimator.NUM_BYTES_OBJECT_REF)][];
430 System.arraycopy(array, 0, newArray, 0, array.length);
431 return newArray;
432 } else {
433 return array;
434 }
435 }
436
437 public static int[][] grow(int[][] array) {
438 return grow(array, 1 + array.length);
439 }
440
441 public static int[][] shrink(int[][] array, int targetSize) {
442 assert targetSize >= 0: "size must be positive (got " + targetSize + "): likely integer overflow?";
443 final int newSize = getShrinkSize(array.length, targetSize, RamUsageEstimator.NUM_BYTES_OBJECT_REF);
444 if (newSize != array.length) {
445 int[][] newArray = new int[newSize][];
446 System.arraycopy(array, 0, newArray, 0, newSize);
447 return newArray;
448 } else {
449 return array;
450 }
451 }
452
453 public static float[][] grow(float[][] array, int minSize) {
454 assert minSize >= 0: "size must be positive (got " + minSize + "): likely integer overflow?";
455 if (array.length < minSize) {
456 float[][] newArray = new float[oversize(minSize, RamUsageEstimator.NUM_BYTES_OBJECT_REF)][];
457 System.arraycopy(array, 0, newArray, 0, array.length);
458 return newArray;
459 } else {
460 return array;
461 }
462 }
463
464 public static float[][] grow(float[][] array) {
465 return grow(array, 1 + array.length);
466 }
467
468 public static float[][] shrink(float[][] array, int targetSize) {
469 assert targetSize >= 0: "size must be positive (got " + targetSize + "): likely integer overflow?";
470 final int newSize = getShrinkSize(array.length, targetSize, RamUsageEstimator.NUM_BYTES_OBJECT_REF);
471 if (newSize != array.length) {
472 float[][] newArray = new float[newSize][];
473 System.arraycopy(array, 0, newArray, 0, newSize);
474 return newArray;
475 } else {
476 return array;
477 }
478 }
479
480
481
482
483
484 public static int hashCode(char[] array, int start, int end) {
485 int code = 0;
486 for (int i = end - 1; i >= start; i--)
487 code = code * 31 + array[i];
488 return code;
489 }
490
491
492
493
494
495 public static int hashCode(byte[] array, int start, int end) {
496 int code = 0;
497 for (int i = end - 1; i >= start; i--)
498 code = code * 31 + array[i];
499 return code;
500 }
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516 public static boolean equals(char[] left, int offsetLeft, char[] right, int offsetRight, int length) {
517 if ((offsetLeft + length <= left.length) && (offsetRight + length <= right.length)) {
518 for (int i = 0; i < length; i++) {
519 if (left[offsetLeft + i] != right[offsetRight + i]) {
520 return false;
521 }
522
523 }
524 return true;
525 }
526 return false;
527 }
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542 public static boolean equals(byte[] left, int offsetLeft, byte[] right, int offsetRight, int length) {
543 if ((offsetLeft + length <= left.length) && (offsetRight + length <= right.length)) {
544 for (int i = 0; i < length; i++) {
545 if (left[offsetLeft + i] != right[offsetRight + i]) {
546 return false;
547 }
548
549 }
550 return true;
551 }
552 return false;
553 }
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597 public static boolean equals(int[] left, int offsetLeft, int[] right, int offsetRight, int length) {
598 if ((offsetLeft + length <= left.length) && (offsetRight + length <= right.length)) {
599 for (int i = 0; i < length; i++) {
600 if (left[offsetLeft + i] != right[offsetRight + i]) {
601 return false;
602 }
603
604 }
605 return true;
606 }
607 return false;
608 }
609
610 public static int[] toIntArray(Collection<Integer> ints) {
611
612 final int[] result = new int[ints.size()];
613 int upto = 0;
614 for(int v : ints) {
615 result[upto++] = v;
616 }
617
618
619 assert upto == result.length;
620
621 return result;
622 }
623
624 private static class NaturalComparator<T extends Comparable<? super T>> implements Comparator<T> {
625 NaturalComparator() {}
626 @Override
627 public int compare(T o1, T o2) {
628 return o1.compareTo(o2);
629 }
630 }
631
632 private static final Comparator<?> NATURAL_COMPARATOR = new NaturalComparator<>();
633
634
635 @SuppressWarnings("unchecked")
636 public static <T extends Comparable<? super T>> Comparator<T> naturalComparator() {
637 return (Comparator<T>) NATURAL_COMPARATOR;
638 }
639
640
641 public static <T> void swap(T[] arr, int i, int j) {
642 final T tmp = arr[i];
643 arr[i] = arr[j];
644 arr[j] = tmp;
645 }
646
647
648
649
650
651
652
653
654
655 public static <T> void introSort(T[] a, int fromIndex, int toIndex, Comparator<? super T> comp) {
656 if (toIndex-fromIndex <= 1) return;
657 new ArrayIntroSorter<>(a, comp).sort(fromIndex, toIndex);
658 }
659
660
661
662
663
664 public static <T> void introSort(T[] a, Comparator<? super T> comp) {
665 introSort(a, 0, a.length, comp);
666 }
667
668
669
670
671
672
673
674 public static <T extends Comparable<? super T>> void introSort(T[] a, int fromIndex, int toIndex) {
675 if (toIndex-fromIndex <= 1) return;
676 introSort(a, fromIndex, toIndex, ArrayUtil.<T>naturalComparator());
677 }
678
679
680
681
682
683 public static <T extends Comparable<? super T>> void introSort(T[] a) {
684 introSort(a, 0, a.length);
685 }
686
687
688
689
690
691
692
693
694
695 public static <T> void timSort(T[] a, int fromIndex, int toIndex, Comparator<? super T> comp) {
696 if (toIndex-fromIndex <= 1) return;
697 new ArrayTimSorter<>(a, comp, a.length / 64).sort(fromIndex, toIndex);
698 }
699
700
701
702
703
704 public static <T> void timSort(T[] a, Comparator<? super T> comp) {
705 timSort(a, 0, a.length, comp);
706 }
707
708
709
710
711
712
713
714 public static <T extends Comparable<? super T>> void timSort(T[] a, int fromIndex, int toIndex) {
715 if (toIndex-fromIndex <= 1) return;
716 timSort(a, fromIndex, toIndex, ArrayUtil.<T>naturalComparator());
717 }
718
719
720
721
722
723 public static <T extends Comparable<? super T>> void timSort(T[] a) {
724 timSort(a, 0, a.length);
725 }
726
727 }